#include "gpio.h"
#include "LPC17xx.h"
#include "clock.h"
#include "interrupt.h"
#include "uart.h"
#include "pin_config.h"
#include "type.h"
#include "status.h"

/**
 * GPIO initialization
 *
 * @param  none
 * @return none
 *
 * @brief  switch on power for pin block
 *
 */
void gpio_init(void)
{
    /* power on periphery */
    SC->PCONP |=  GPIO_POWERON;

}

/**
 * GPIO configuration
 *
 * @param  uint32_t8_t bank LPC register bank
 * @param  uint8_t pin LPC controller pin
 * @param  uint8_t direction LPC pin direction
 * @return none
 *
 * @brief  configure pin as input/output/floating
 *
 */
void gpio_configure(uint8_t bank, uint8_t pin, uint8_t direction)
{
    uint32_t mask = 0;

    /* set mask for deleting the former setting */
    mask = ~(1 << pin);


    switch(bank)
    {
    case BANK_0:
        GPIO0->FIODIR &= mask;
        GPIO0->FIODIR |= (direction << pin);
        break;
    case BANK_1:
        GPIO1->FIODIR &= mask;
        GPIO1->FIODIR |= (direction << pin);
        break;
    case BANK_2:
        GPIO2->FIODIR &= mask;
        GPIO2->FIODIR |= (direction << pin);
        break;
    case BANK_3:
        GPIO3->FIODIR &= mask;
        GPIO3->FIODIR |= (direction << pin);
        break;
    case BANK_4:
        GPIO4->FIODIR &= mask;
        GPIO4->FIODIR |= (direction << pin);
        break;
    default:
        break;
    }
}

/**
 * set gpio pin
 *
 * @param  uint8_t bank LPC register bank
 * @param  uint8_t pin LPC controller pin
 * @param  uint8_t Setting ON/OFF
 * @return none
 *
 * @brief  set controller gpio pin to 1/0
 *
 */
uint32_t gpio_set(uint8_t bank, uint8_t pin, uint8_t setting)
{
    switch(bank)
    {
    case BANK_0:
        if (setting == 1)
        {
            GPIO0->FIOSET |= (1 << pin);
        }
        else
        {
            GPIO0->FIOCLR |= (1 << pin);
        }
        break;
    case BANK_1:
        if (setting == 1)
        {
            GPIO1->FIOSET |= (1 << pin);
        }
        else
        {
            GPIO1->FIOCLR |= (1 << pin);
        }
        break;
    case BANK_2:
        if (setting == 1)
        {
            GPIO2->FIOSET |= (1 << pin);
        }
        else
        {
            GPIO2->FIOCLR |= (1 << pin);
        }
        break;
    case BANK_3:
        if (setting == 1)
        {
            GPIO3->FIOSET |= (1 << pin);
        }
        else
        {
            GPIO3->FIOCLR |= (1 << pin);
        }
        break;
    case BANK_4:
        if (setting == 1)
        {
            GPIO4->FIOSET |= (1 << pin);
        }
        else
        {
            GPIO4->FIOCLR |= (1 << pin);
        }
        break;
    default:
    	return STATUS_ERROR_ACCESS;
        break;
    }
    return STATUS_OK;
}

/**
 * get gpio pin
 *
 * @param  uint8_t bank LPC register bank
 * @param  uint8_t pin LPC controller pin
 * @return uint8_t Setting ON/OFF
 *
 * @brief  get controller gpio pin state 1/0
 *
 */
uint8_t gpio_get(uint8_t bank, uint8_t pin)
{
    switch(bank)
    {
    case BANK_0:
        if(GPIO0->FIOPIN & (1 << pin))
            return 1;
        break;
    case BANK_1:
        if(GPIO1->FIOPIN & (1 << pin))
            return 1;
        break;
    case BANK_2:
        if(GPIO2->FIOPIN & (1 << pin))
            return 1;
        break;
    case BANK_3:
        if(GPIO3->FIOPIN & (1 << pin))
            return 1;
        break;
    case BANK_4:
        if(GPIO4->FIOPIN & (1 << pin))
            return 1;
        break;
    default:
        break;
    }
    return 0;
}

